package com.caisejingyu.whales.common.api.interceptor;

import android.os.Build;
import android.support.annotation.NonNull;
import android.text.TextUtils;
import android.util.Log;
import android.widget.Toast;

import com.caisejingyu.whales.common.BaseApplication;
import com.caisejingyu.whales.common.BuildConfig;
import com.google.gson.Gson;
import com.caisejingyu.whales.common.AppConfig;
import com.caisejingyu.whales.common.api.ApiConfig;
import com.caisejingyu.whales.common.utils.FormatUtil;
import com.caisejingyu.whales.common.utils.SignUtil;

import org.json.JSONException;
import org.json.JSONObject;

import java.io.IOException;
import java.net.ConnectException;
import java.net.UnknownHostException;
import java.util.List;
import java.util.Map;

import okhttp3.HttpUrl;
import okhttp3.Interceptor;
import okhttp3.MediaType;
import okhttp3.Protocol;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;
import okhttp3.ResponseBody;
import okhttp3.internal.Util;
import okio.Buffer;

import static com.caisejingyu.whales.common.api.ApiConfig.URL_KEY_HEADER;


/**
 * 抽象拦截器
 */
@SuppressWarnings({"WeakerAccess", "unused"})
class AbsInterceptor implements Interceptor {

    public static final String TAG = AbsInterceptor.class.getSimpleName();

    private static final String GET = "GET";
    private static final String DELETE = "DELETE";
    private static final String POST = "POST";
    private static final String PUT = "PUT";
    private static final String NETWORK_ERROR_HINT = "当前网络不可用，请检查网络连接";

    // 避免多次创建builder对象
    public volatile Response.Builder responseBuilder = new Response.Builder();

    final ApiConfig mApiConfig;

    AbsInterceptor(@NonNull ApiConfig apiConfig) {
        mApiConfig = apiConfig;
    }

    @Override
    public Response intercept(Chain chain) throws IOException {
        boolean isSuccessful = false;
        Request.Builder builder = chain.request().newBuilder();
        HttpUrl newHttpUrl = processReplaceBaseUrl(chain, builder);
        String baseUrl = mApiConfig.getBaseUrl();
        if (newHttpUrl != null) {
            baseUrl = newHttpUrl.url().toString();
            newHttpUrl = chain.request().url()
                    .newBuilder()
                    .scheme(newHttpUrl.scheme())
                    .host(newHttpUrl.host())
                    .port(newHttpUrl.port())
                    .build();
            builder.url(newHttpUrl);
        }

        appendHeader(builder);
        Request request = builder.build();
        switch (request.method()) {
            case GET:
            case DELETE:
                processGetOrDelete(builder, baseUrl);
                break;
            case PUT:
            case POST:
                try {
                    processPutOrPost(builder, baseUrl);
                } catch (IOException ignore) {
                }
                break;
            default:
                break;
        }
        IOException exception;
        try {
            Response response = chain.proceed(builder.build());
            return processResponse(response);
        } catch (UnknownHostException e) {
            Log.i(TAG, "UnknownHostException" + e.getMessage());
            exception = e;
        } catch (ConnectException e) {
            Log.i(TAG, "ConnectException" + e.getMessage());
            exception = e;
        } catch (IOException e) {
            Log.i(TAG, "IOException" + e.getMessage());
            exception = e;
        }
        throw exception;
    }

    private HttpUrl processReplaceBaseUrl(Chain chain, Request.Builder builder) {
        List<String> headers = chain.request().headers(URL_KEY_HEADER);
        if (headers != null && !headers.isEmpty()) {
            builder.removeHeader(URL_KEY_HEADER);
            String urlKey = headers.get(0);
            if (!TextUtils.isEmpty(urlKey)) {
                String url = mApiConfig.getUrlMap().get(urlKey);
                if (!TextUtils.isEmpty(url)) {
                    return HttpUrl.parse(url);
                }
            }
        }
        return null;
    }

    Request.Builder appendHeader(Request.Builder builder) {
        builder
                .addHeader("source", AppConfig.getInstance().getAppType())
                .addHeader("model", AppConfig.getInstance().getModel())
                .addHeader("localsizeModel", AppConfig.getInstance().getAppName())
                .addHeader("systemName", AppConfig.getInstance().getSystemName())
                .addHeader("systemVersion", AppConfig.getInstance().getSystemVersion())
                .addHeader("mobileId", AppConfig.getInstance().getMobileId())
                .addHeader("mobileName", AppConfig.getInstance().getMobileName())
                .addHeader("appVersion", AppConfig.getInstance().getAppVersion());
        return builder;
    }

    void processGetOrDelete(Request.Builder builder, String baseUrl) {
        final String url = builder.build().url().toString();
        final String timestamp = Long.toString(System.currentTimeMillis());
        String path = "/" + url.replace(baseUrl, "");
        path = String.format("%s%sappId=%s&timestamp=%s&secret=%s", path, getSeparator(path),
                mApiConfig.getAppId(), timestamp, mApiConfig.getAppSecret());
        final String sign = SignUtil.encryptMD5(path);
        builder
                .addHeader("sign", FormatUtil.formatEmpty(sign))
                .addHeader("signType", "MD5")
                .url(String.format("%s%sappId=%s&timestamp=%s&_c=%s",
                        url, getSeparator(url), mApiConfig.getAppId(), timestamp, mApiConfig.getMachine()));
    }

    void processPutOrPost(Request.Builder builder, String baseUrl) throws IOException {
        final String url = builder.build().url().toString();
        final String timestamp = Long.toString(System.currentTimeMillis());
        String path = "/" + url.replace(baseUrl, "");

        RequestBody requestBody = builder.build().body();
        String body = "";
        // 获取请求体
        if (requestBody != null) {
            Buffer buffer = new Buffer();
            requestBody.writeTo(buffer);
            body = buffer.readUtf8();
        }
        try {
            JSONObject jsonObject = new JSONObject();
            if (!TextUtils.isEmpty(body)) {
                jsonObject = new JSONObject(body);
            }
            // 增加签名参数
            String data = String.format("data=%s&path=%s&secret=%s", body, path, mApiConfig.getAppSecret());

            final String sign = SignUtil.getSign(getUrl(body.toString(), path));
            jsonObject.put("sign", sign);
//            jsonObject.put("_c", Build.SERIAL);
            body = jsonObject.toString();
            builder
                    .method(builder.build().method(), RequestBody.create(requestBody == null ? null : requestBody.contentType(), body));
        } catch (JSONException e) {
            e.printStackTrace();
        }
    }

    Response processResponse(@NonNull Response response) throws IOException, NullPointerException {
        return response;
    }

    private String getUrl(String json, String path) {
        StringBuilder stringBuilder = new StringBuilder();
        Map<String, String> map = new Gson().fromJson(json, Map.class);

        stringBuilder.append(path);
        stringBuilder.append("?");
        for (Map.Entry<String, String> entry : map.entrySet()) {
            stringBuilder.append(entry.getKey());
            stringBuilder.append("=");
            stringBuilder.append(entry.getValue());
            stringBuilder.append("&");
        }
        stringBuilder.deleteCharAt(stringBuilder.length() - 1);
        return stringBuilder.toString();
    }

    private String getSeparator(String url) {
        return url.contains("?") ? "&" : "?";
    }
}